home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / TrackList.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  26.3 KB  |  925 lines  |  [TEXT/KAHL]

  1. /* TrackList.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "TrackList.h"
  31. #include "StringList.h"
  32. #include "Array.h"
  33. #include "Memory.h"
  34. #include "TrackObject.h"
  35. #include "Alert.h"
  36. #include "DataMunging.h"
  37. #include "Menus.h"
  38. #include "BufferedFileInput.h"
  39. #include "BufferedFileOutput.h"
  40. #include "Files.h"
  41. #include "Scrap.h"
  42. #include "TrackBackgroundSaver.h"
  43.  
  44.  
  45. struct TrackListRec
  46.     {
  47.         StringListRec*                    List;
  48.         struct CodeCenterRec*        CodeCenter;
  49.         struct MainWindowRec*        MainWindow;
  50.         ArrayRec*                                TrackArray;
  51.         MyBoolean                                TrackListChanged;
  52.         MenuType*                                TrackMenu;
  53.     };
  54.  
  55.  
  56. #define MAGICSCRAPSTRING ("\xff\x00\x1f\xfe TrackObjectScrap")
  57.  
  58.  
  59. /* create a new track list */
  60. TrackListRec*                NewTrackList(struct MainWindowRec* MainWindow,
  61.                                             struct CodeCenterRec* CodeCenter, WinType* ScreenID,
  62.                                             OrdType XLoc, OrdType YLoc, OrdType Width, OrdType Height)
  63.     {
  64.         TrackListRec*            TrackList;
  65.  
  66.         TrackList = (TrackListRec*)AllocPtrCanFail(sizeof(TrackListRec),"TrackListRec");
  67.         if (TrackList == NIL)
  68.             {
  69.              FailurePoint1:
  70.                 return NIL;
  71.             }
  72.         TrackList->TrackArray = NewArray();
  73.         if (TrackList->TrackArray == NIL)
  74.             {
  75.              FailurePoint2:
  76.                 ReleasePtr((char*)TrackList);
  77.                 goto FailurePoint1;
  78.             }
  79.         TrackList->List = NewStringList(ScreenID,XLoc,YLoc,Width,Height,
  80.             GetScreenFont(),9,StringListDontAllowMultipleSelection,"Tracks");
  81.         if (TrackList->List == NIL)
  82.             {
  83.              FailurePoint3:
  84.                 DisposeArray(TrackList->TrackArray);
  85.                 goto FailurePoint2;
  86.             }
  87.         TrackList->TrackMenu = MakeNewMenu("Tracks");
  88.         if (TrackList->TrackMenu == NIL)
  89.             {
  90.              FailurePoint4:
  91.                 DisposeStringList(TrackList->List);
  92.                 goto FailurePoint3;
  93.             }
  94.         TrackList->CodeCenter = CodeCenter;
  95.         TrackList->MainWindow = MainWindow;
  96.         TrackList->TrackListChanged = False;
  97.         return TrackList;
  98.     }
  99.  
  100.  
  101. /* delete the track list and all of the tracks it contains */
  102. void                                DisposeTrackList(TrackListRec* TrackList)
  103.     {
  104.         CheckPtrExistence(TrackList);
  105.         while (ArrayGetLength(TrackList->TrackArray) > 0)
  106.             {
  107.                 TrackObjectRec*        TrackTemp;
  108.  
  109.                 TrackTemp = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,0);
  110.                 /* we remove it from the array since deleting it may cause a callback */
  111.                 /* to tell others that it is being deleted, so we don't want to have */
  112.                 /* nonexistent objects in our array */
  113.                 ArrayDeleteElement(TrackList->TrackArray,0);
  114.                 DisposeTrackObject(TrackTemp);
  115.             }
  116.         DisposeArray(TrackList->TrackArray);
  117.         DisposeStringList(TrackList->List);
  118.         KillMenuAndDeleteItems(TrackList->TrackMenu);
  119.         ReleasePtr((char*)TrackList);
  120.     }
  121.  
  122.  
  123. /* change the location of the track list in the window */
  124. void                                SetTrackListLocation(TrackListRec* TrackList,
  125.                                             OrdType XLoc, OrdType YLoc, OrdType Width, OrdType Height)
  126.     {
  127.         CheckPtrExistence(TrackList);
  128.         SetStringListLoc(TrackList->List,XLoc,YLoc,Width,Height);
  129.     }
  130.  
  131.  
  132. /* redraw the list */
  133. void                                TrackListRedraw(TrackListRec* TrackList)
  134.     {
  135.         CheckPtrExistence(TrackList);
  136.         RedrawStringList(TrackList->List);
  137.     }
  138.  
  139.  
  140. /* see if the specified coordinates falls inside the track list rectangle */
  141. MyBoolean                        TrackListHitTest(TrackListRec* TrackList,
  142.                                             OrdType XLoc, OrdType YLoc)
  143.     {
  144.         CheckPtrExistence(TrackList);
  145.         return StringListHitTest(TrackList->List,XLoc,YLoc);
  146.     }
  147.  
  148.  
  149. /* handle a mouse down event for the track list */
  150. void                                TrackListDoMouseDown(TrackListRec* TrackList,
  151.                                             OrdType XLoc, OrdType YLoc, ModifierFlags Modifiers)
  152.     {
  153.         CheckPtrExistence(TrackList);
  154.         if (StringListMouseDown(TrackList->List,XLoc,YLoc,Modifiers))
  155.             {
  156.                 /* if it returns true, then it was a double click */
  157.                 TrackListOpenSelection(TrackList);
  158.             }
  159.     }
  160.  
  161.  
  162. /* called when the window becomes active */
  163. void                                TrackListBecomeActive(TrackListRec* TrackList)
  164.     {
  165.         CheckPtrExistence(TrackList);
  166.         EnableStringList(TrackList->List);
  167.     }
  168.  
  169.  
  170. /* called when the window becomes inactive */
  171. void                                TrackListBecomeInactive(TrackListRec* TrackList)
  172.     {
  173.         CheckPtrExistence(TrackList);
  174.         DisableStringList(TrackList->List);
  175.     }
  176.  
  177.  
  178. /* called when a selection is made in another list, so that this list */
  179. /* is deselected */
  180. void                                TrackListDeselect(TrackListRec* TrackList)
  181.     {
  182.         CheckPtrExistence(TrackList);
  183.         DeselectAllStringListElements(TrackList->List);
  184.     }
  185.  
  186.  
  187. /* check to see if there is a selection in this list */
  188. MyBoolean                        TrackListIsThereSelection(TrackListRec* TrackList)
  189.     {
  190.         CheckPtrExistence(TrackList);
  191.         return (GetStringListHowManySelectedItems(TrackList->List) > 0);
  192.     }
  193.  
  194.  
  195. /* check to see if any of the tracks contained in this list need to be saved */
  196. MyBoolean                        DoesTrackListNeedToBeSaved(TrackListRec* TrackList)
  197.     {
  198.         long                            Scan;
  199.         long                            Limit;
  200.         MyBoolean                    Flag;
  201.  
  202.         CheckPtrExistence(TrackList);
  203.         Flag = TrackList->TrackListChanged;
  204.         Limit = ArrayGetLength(TrackList->TrackArray);
  205.         for (Scan = 0; (Scan < Limit) && !Flag; Scan += 1)
  206.             {
  207.                 TrackObjectRec*        TrackTemp;
  208.  
  209.                 TrackTemp = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  210.                 if (HasTrackObjectBeenModified(TrackTemp))
  211.                     {
  212.                         Flag = True;
  213.                     }
  214.             }
  215.         return Flag;
  216.     }
  217.  
  218.  
  219. /* open an edit window for the selected track */
  220. void                                TrackListOpenSelection(TrackListRec* TrackList)
  221.     {
  222.         ArrayRec*                    ListOfSelections;
  223.  
  224.         CheckPtrExistence(TrackList);
  225.         ListOfSelections = GetListOfSelectedItems(TrackList->List);
  226.         if (ListOfSelections != NIL)
  227.             {
  228.                 long                            Scan;
  229.                 long                            Limit;
  230.  
  231.                 Limit = ArrayGetLength(ListOfSelections);
  232.                 for (Scan = 0; Scan < Limit; Scan += 1)
  233.                     {
  234.                         TrackObjectRec*        TrackTemp;
  235.  
  236.                         TrackTemp = (TrackObjectRec*)ArrayGetElement(ListOfSelections,Scan);
  237.                         TrackObjectOpenWindow(TrackTemp);
  238.                     }
  239.                 DisposeArray(ListOfSelections);
  240.             }
  241.     }
  242.  
  243.  
  244. /* create a new track and open a window for it */
  245. void                                TrackListNewTrack(TrackListRec* TrackList)
  246.     {
  247.         TrackObjectRec*        Track;
  248.  
  249.         CheckPtrExistence(TrackList);
  250.         /* create the object */
  251.         Track = NewTrackObject(TrackList->CodeCenter,TrackList->MainWindow,TrackList);
  252.         if (Track == NIL)
  253.             {
  254.              FailurePoint1:
  255.                 AlertHalt("There is not enough memory available to create a new track.",NIL);
  256.                 return;
  257.             }
  258.         /* add it to the string list */
  259.         if (!InsertStringListElement(TrackList->List,NIL,NIL,Track,True))
  260.             {
  261.              FailurePoint2:
  262.                 DisposeTrackObject(Track);
  263.                 goto FailurePoint1;
  264.             }
  265.         MainWindowDeselectAllOtherStringLists(TrackList->MainWindow,TrackList);
  266.         SelectStringListElement(TrackList->List,Track);
  267.         MakeStringListSelectionVisible(TrackList->List);
  268.         /* add it to the array */
  269.         if (!ArrayAppendElement(TrackList->TrackArray,Track))
  270.             {
  271.              FailurePoint3:
  272.                 RemoveStringListElement(TrackList->List,Track,True);
  273.                 goto FailurePoint2;
  274.             }
  275.         /* update our internal flags */
  276.         TrackList->TrackListChanged = True;
  277.         /* change the name in the list */
  278.         TrackListTrackNameChanged(TrackList,Track);
  279.         /* show the window */
  280.         TrackObjectOpenWindow(Track);
  281.     }
  282.  
  283.  
  284. /* delete the selected track */
  285. void                                TrackListDeleteSelection(TrackListRec* TrackList)
  286.     {
  287.         ArrayRec*                    ListOfSelections;
  288.  
  289.         CheckPtrExistence(TrackList);
  290.         ListOfSelections = GetListOfSelectedItems(TrackList->List);
  291.         if (ListOfSelections != NIL)
  292.             {
  293.                 long                                Scan;
  294.                 long                                Limit;
  295.  
  296.                 Limit = ArrayGetLength(ListOfSelections);
  297.                 for (Scan = 0; Scan < Limit; Scan += 1)
  298.                     {
  299.                         TrackObjectRec*            OneToZap;
  300.  
  301.                         OneToZap = (TrackObjectRec*)ArrayGetElement(ListOfSelections,Scan);
  302.                         TrackListDeleteTrack(TrackList,OneToZap);
  303.                     }
  304.                 DisposeArray(ListOfSelections);
  305.             }
  306.     }
  307.  
  308.  
  309. /* delete the explicitly specified track */
  310. void                                TrackListDeleteTrack(TrackListRec* TrackList,
  311.                                             struct TrackObjectRec* TheTrack)
  312.     {
  313.         long                                Scan;
  314.         long                                Limit;
  315.  
  316.         CheckPtrExistence(TrackList);
  317.         Limit = ArrayGetLength(TrackList->TrackArray);
  318.         for (Scan = 0; Scan < Limit; Scan += 1)
  319.             {
  320.                 TrackObjectRec*            TrackTemp;
  321.  
  322.                 TrackTemp = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  323.                 if (TheTrack == TrackTemp)
  324.                     {
  325.                         FileSpec*                    BackupFileWhere;
  326.                         FileType*                    BackupFile;
  327.                         MyBoolean                    Success = False;
  328.  
  329.                         BackupFileWhere = NewTempFileSpec(CODE4BYTES('?','?','?','?'),
  330.                             CODE4BYTES('?','?','?','?'));
  331.                         if (BackupFileWhere != NIL)
  332.                             {
  333.                                 if (OpenFile(BackupFileWhere,&BackupFile,eReadAndWrite))
  334.                                     {
  335.                                         BufferedOutputRec*    Output;
  336.  
  337.                                         Output = NewBufferedOutput(BackupFile);
  338.                                         if (Output != NIL)
  339.                                             {
  340.                                                 if (WriteBufferedOutput(Output,sizeof(MAGICSCRAPSTRING),
  341.                                                     MAGICSCRAPSTRING))
  342.                                                     {
  343.                                                         if (TrackObjectWriteDataOut(TheTrack,Output)
  344.                                                             == eFileLoadNoError)
  345.                                                             {
  346.                                                                 Success = True;
  347.                                                             }
  348.                                                     }
  349.                                                 if (!EndBufferedOutput(Output))
  350.                                                     {
  351.                                                         Success = False;
  352.                                                     }
  353.                                             }
  354.                                          else
  355.                                             {
  356.                                                 CloseFile(BackupFile);
  357.                                             }
  358.                                     }
  359.                                  else
  360.                                     {
  361.                                         DeleteFile(BackupFileWhere);
  362.                                         DisposeFileSpec(BackupFileWhere);
  363.                                     }
  364.                             }
  365.                         if (Success)
  366.                             {
  367.                                 MainWindowNewDeleteUndoInfo(TrackList->MainWindow,BackupFileWhere,
  368.                                     BackupFile);
  369.                                 DisposeTrackObject(TrackTemp);
  370.                                 RemoveStringListElement(TrackList->List,TrackTemp,True);
  371.                                 ArrayDeleteElement(TrackList->TrackArray,Scan);
  372.                                 TrackList->TrackListChanged = True;
  373.                             }
  374.                          else
  375.                             {
  376.                                 YesNoCancelType        Decision;
  377.  
  378.                                 Decision = AskYesNoCancel("Unable to save undo information for object.  "
  379.                                     "Delete object anyway?",NIL,"Delete","Cancel",NIL/*nothirdbutton*/);
  380.                                 if (Decision == eYes)
  381.                                     {
  382.                                         DisposeTrackObject(TrackTemp);
  383.                                         RemoveStringListElement(TrackList->List,TrackTemp,True);
  384.                                         ArrayDeleteElement(TrackList->TrackArray,Scan);
  385.                                         TrackList->TrackListChanged = True;
  386.                                     }
  387.                             }
  388.                         return;
  389.                     }
  390.             }
  391.         EXECUTE(PRERR(AllowResume,"TrackListDeleteTrack:  couldn't find object"));
  392.     }
  393.  
  394.  
  395. /* the name of an track has changed, so the name in the scrolling */
  396. /* list must also be changed */
  397. void                                TrackListTrackNameChanged(TrackListRec* TrackList,
  398.                                             struct TrackObjectRec* TheTrack)
  399.     {
  400.         char*                            TrackName;
  401.  
  402.         CheckPtrExistence(TrackList);
  403.         CheckPtrExistence(TheTrack);
  404.         ERROR(ArrayFindElement(TrackList->TrackArray,TheTrack) < 0,
  405.             PRERR(ForceAbort,"TrackListTrackNameChanged:  unknown track"));
  406.         TrackName = TrackObjectGetNameCopy(TheTrack);
  407.         if (TrackName != NIL)
  408.             {
  409.                 char*                            TrackNameNullTerminated;
  410.  
  411.                 TrackNameNullTerminated = BlockToStringCopy(TrackName);
  412.                 if (TrackNameNullTerminated != NIL)
  413.                     {
  414.                         ChangeStringListElementName(TrackList->List,
  415.                             TrackNameNullTerminated,TheTrack);
  416.                         ReleasePtr(TrackNameNullTerminated);
  417.                     }
  418.                 ReleasePtr(TrackName);
  419.             }
  420.     }
  421.  
  422.  
  423. /* look for a specified track.  returns NIL if not found.  the name is */
  424. /* NOT null terminated */
  425. struct TrackObjectRec*    TrackListLookupNamedTrack(TrackListRec* TrackList, char* Name)
  426.     {
  427.         long                            Scan;
  428.         long                            Limit;
  429.  
  430.         CheckPtrExistence(TrackList);
  431.         CheckPtrExistence(Name);
  432.         Limit = ArrayGetLength(TrackList->TrackArray);
  433.         for (Scan = 0; Scan < Limit; Scan += 1)
  434.             {
  435.                 TrackObjectRec*            Track;
  436.                 char*                                NameCopy;
  437.  
  438.                 Track = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  439.                 NameCopy = TrackObjectGetNameCopy(Track);
  440.                 if (NameCopy != NIL)
  441.                     {
  442.                         if (PtrSize(Name) == PtrSize(NameCopy))
  443.                             {
  444.                                 if (MemEqu(Name,NameCopy,PtrSize(Name)))
  445.                                     {
  446.                                         ReleasePtr(NameCopy);
  447.                                         return Track;
  448.                                     }
  449.                             }
  450.                         ReleasePtr(NameCopy);
  451.                     }
  452.             }
  453.         return NIL;
  454.     }
  455.  
  456.  
  457. /* cancel dependencies where objects have the specified object listed in the */
  458. /* background.  this is called by the specified object when it is dying */
  459. void                                TrackListDelinkBackgroundInstances(TrackListRec* TrackList,
  460.                                             struct TrackObjectRec* TheTrack)
  461.     {
  462.         long                            Scan;
  463.         long                            Limit;
  464.  
  465.         CheckPtrExistence(TrackList);
  466.         CheckPtrExistence(TheTrack);
  467.         Limit = ArrayGetLength(TrackList->TrackArray);
  468.         for (Scan = 0; Scan < Limit; Scan += 1)
  469.             {
  470.                 TrackObjectRec*            Track;
  471.  
  472.                 Track = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  473.                 if (Track != TheTrack)
  474.                     {
  475.                         TrackObjectRemoveBackgroundObj(Track/*listowner*/,TheTrack/*onetoremove*/);
  476.                     }
  477.             }
  478.     }
  479.  
  480.  
  481. /* get the track menu */
  482. MenuType*                        TrackListGetTrackMenu(TrackListRec* TrackList)
  483.     {
  484.         CheckPtrExistence(TrackList);
  485.         return TrackList->TrackMenu;
  486.     }
  487.  
  488.  
  489. /* enable all of the menu items on the menu associated with this track list */
  490. void                                TrackListEnableMenuItems(TrackListRec* TrackList)
  491.     {
  492.         long                            Scan;
  493.         long                            Limit;
  494.  
  495.         CheckPtrExistence(TrackList);
  496.         Limit = ArrayGetLength(TrackList->TrackArray);
  497.         for (Scan = 0; Scan < Limit; Scan += 1)
  498.             {
  499.                 EnableMenuItem(TrackObjectGetMenuItem((TrackObjectRec*)ArrayGetElement(
  500.                     TrackList->TrackArray,Scan)));
  501.             }
  502.     }
  503.  
  504.  
  505. /* return the track object associated with the specified menu item or NIL if */
  506. /* there is no such track object */
  507. struct TrackObjectRec*    TrackListLookupMenuItem(TrackListRec* TrackList,
  508.                                             struct MenuItemType* MenuItem)
  509.     {
  510.         long                            Scan;
  511.         long                            Limit;
  512.  
  513.         CheckPtrExistence(TrackList);
  514.         Limit = ArrayGetLength(TrackList->TrackArray);
  515.         for (Scan = 0; Scan < Limit; Scan += 1)
  516.             {
  517.                 TrackObjectRec*        TrackObj;
  518.  
  519.                 TrackObj = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  520.                 if (TrackObjectGetMenuItem(TrackObj) == MenuItem)
  521.                     {
  522.                         return TrackObj;
  523.                     }
  524.             }
  525.         return NIL;
  526.     }
  527.  
  528.  
  529. /* put a checkmark on all track menu items that occur in this list */
  530. void                                TrackListMenuItemCheckmarks(TrackListRec* TrackList,
  531.                                             ArrayRec* TrackObjList)
  532.     {
  533.         long                            Limit;
  534.         long                            Scan;
  535.         long                            OtherLimit;
  536.  
  537.         CheckPtrExistence(TrackList);
  538.         CheckPtrExistence(TrackObjList);
  539.         Limit = ArrayGetLength(TrackList->TrackArray);
  540.         OtherLimit = ArrayGetLength(TrackObjList);
  541.         for (Scan = 0; Scan < Limit; Scan += 1)
  542.             {
  543.                 long                            OtherScan;
  544.                 TrackObjectRec*        PossibleTrack;
  545.  
  546.                 PossibleTrack = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  547.                 for (OtherScan = 0; OtherScan < OtherLimit; OtherScan += 1)
  548.                     {
  549.                         TrackObjectRec*        Checkable;
  550.  
  551.                         Checkable = (TrackObjectRec*)ArrayGetElement(TrackObjList,OtherScan);
  552.                         if (Checkable == PossibleTrack)
  553.                             {
  554.                                 SetItemCheckmark(TrackObjectGetMenuItem(Checkable));
  555.                                 goto FoundItPoint;
  556.                             }
  557.                     }
  558.                 /* jump here when it is found */
  559.              FoundItPoint:
  560.                 ;
  561.             }
  562.     }
  563.  
  564.  
  565. /* the document's name changed, so we need to update the windows */
  566. void                                TrackListGlobalNameChange(TrackListRec* TrackList, char* NewFilename)
  567.     {
  568.         long                            Scan;
  569.         long                            Limit;
  570.  
  571.         CheckPtrExistence(TrackList);
  572.         Limit = ArrayGetLength(TrackList->TrackArray);
  573.         for (Scan = 0; Scan < Limit; Scan += 1)
  574.             {
  575.                 TrackObjectRec*        TrackObj;
  576.  
  577.                 TrackObj = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  578.                 TrackObjectGlobalNameChange(TrackObj,NewFilename);
  579.             }
  580.     }
  581.  
  582.  
  583. /* get an array of all of the tracks.  it must be disposed of by the caller */
  584. struct ArrayRec*        TrackListGetListOfAllTracks(TrackListRec* TrackList)
  585.     {
  586.         CheckPtrExistence(TrackList);
  587.         return DuplicateArray(TrackList->TrackArray);
  588.     }
  589.  
  590.  
  591. /*   4-byte little endian number of tracks (positive 2s complement) */
  592. /*   n-bytes data for the track objects */
  593. /*   n-bytes data for background display information (a chunk for each track) */
  594.  
  595.  
  596. /* read track data from a file.  returns True if completely successful. */
  597. FileLoadingErrors        TrackListReadData(TrackListRec* TrackList,
  598.                                             struct BufferedInputRec* Input)
  599.     {
  600.         signed long                NumberOfTracks;
  601.         long                            Scan;
  602.  
  603.         CheckPtrExistence(TrackList);
  604.         CheckPtrExistence(Input);
  605.  
  606.         /*   4-byte little endian number of tracks (positive 2s complement) */
  607.         if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfTracks))
  608.             {
  609.                 return eFileLoadDiskError;
  610.             }
  611.         if (NumberOfTracks < 0)
  612.             {
  613.                 return eFileLoadBadFormat;
  614.             }
  615.  
  616.         /*   n-bytes data for objects */
  617.         for (Scan = 0; Scan < NumberOfTracks; Scan += 1)
  618.             {
  619.                 TrackObjectRec*        Track EXECUTE(= (TrackObjectRec*)0x81818181);
  620.                 FileLoadingErrors    Error;
  621.  
  622.                 /* load the track */
  623.                 Error = TrackObjectNewFromFile(&Track,Input,TrackList->CodeCenter,
  624.                     TrackList->MainWindow,TrackList);
  625.                 if (Error != eFileLoadNoError)
  626.                     {
  627.                      FailurePoint1:
  628.                         return Error;
  629.                     }
  630.                 CheckPtrExistence(Track);
  631.                 /* add it to the string list */
  632.                 if (!InsertStringListElement(TrackList->List,NIL,NIL,Track,True))
  633.                     {
  634.                      FailurePoint2:
  635.                         DisposeTrackObject(Track);
  636.                         Error = eFileLoadOutOfMemory;
  637.                         goto FailurePoint1;
  638.                     }
  639.                 /* add it to the array */
  640.                 if (!ArrayAppendElement(TrackList->TrackArray,Track))
  641.                     {
  642.                      FailurePoint3:
  643.                         RemoveStringListElement(TrackList->List,Track,True);
  644.                         goto FailurePoint2;
  645.                     }
  646.                 /* change the name in the list */
  647.                 TrackListTrackNameChanged(TrackList,Track);
  648.             }
  649.  
  650.         for (Scan = 0; Scan < NumberOfTracks; Scan += 1)
  651.             {
  652.                 TrackObjectRec*        Track;
  653.                 FileLoadingErrors    Error;
  654.  
  655.                 Track = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  656.                 CheckPtrExistence(Track);
  657.                 Error = LoadBackgroundTrackInfo(Track,Input,TrackList->TrackArray);
  658.                 if (Error != eFileLoadNoError)
  659.                     {
  660.                         return Error;
  661.                     }
  662.             }
  663.  
  664.         return eFileLoadNoError;
  665.     }
  666.  
  667.  
  668. /* write track data to a file.  returns True if completely successful. */
  669. FileLoadingErrors        TrackListWriteData(TrackListRec* TrackList,
  670.                                             struct BufferedOutputRec* Output)
  671.     {
  672.         long                            NumberOfTracks;
  673.         long                            Scan;
  674.  
  675.         CheckPtrExistence(TrackList);
  676.         CheckPtrExistence(Output);
  677.  
  678.         /*   4-byte little endian number of tracks (positive 2s complement) */
  679.         NumberOfTracks = ArrayGetLength(TrackList->TrackArray);
  680.         if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfTracks))
  681.             {
  682.                 return eFileLoadDiskError;
  683.             }
  684.  
  685.         /*   n-bytes data for objects */
  686.         for (Scan = 0; Scan < NumberOfTracks; Scan += 1)
  687.             {
  688.                 TrackObjectRec*        TrackObj;
  689.                 FileLoadingErrors    Error;
  690.  
  691.                 /* get the track */
  692.                 TrackObj = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  693.                 /* write the track out to disk */
  694.                 Error = TrackObjectWriteDataOut(TrackObj,Output);
  695.                 /* handle errors */
  696.                 if (Error != eFileLoadNoError)
  697.                     {
  698.                         return Error;
  699.                     }
  700.             }
  701.  
  702.         for (Scan = 0; Scan < NumberOfTracks; Scan += 1)
  703.             {
  704.                 TrackObjectRec*        Track;
  705.                 FileLoadingErrors    Error;
  706.  
  707.                 Track = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  708.                 CheckPtrExistence(Track);
  709.                 Error = SaveBackgroundTrackInfo(Track,Output,TrackList->TrackArray);
  710.                 if (Error != eFileLoadNoError)
  711.                     {
  712.                         return Error;
  713.                     }
  714.             }
  715.  
  716.         return eFileLoadNoError;
  717.     }
  718.  
  719.  
  720. /* after a file has been saved, this is called to mark all objects as not modified. */
  721. void                                TrackListMarkAllObjectsSaved(TrackListRec* TrackList)
  722.     {
  723.         long                            Scan;
  724.         long                            Limit;
  725.  
  726.         CheckPtrExistence(TrackList);
  727.         Limit = ArrayGetLength(TrackList->TrackArray);
  728.         for (Scan = 0; Scan < Limit; Scan += 1)
  729.             {
  730.                 TrackObjectRec*        TrackObj;
  731.  
  732.                 TrackObj = (TrackObjectRec*)ArrayGetElement(TrackList->TrackArray,Scan);
  733.                 TrackObjectMarkAsSaved(TrackObj);
  734.             }
  735.         TrackList->TrackListChanged = False;
  736.     }
  737.  
  738.  
  739. /* copy the selected object in the list to the clipboard.  return False if failed. */
  740. MyBoolean                        TrackListCopyObject(TrackListRec* TrackList)
  741.     {
  742.         ArrayRec*                            ListOfSelections;
  743.         MyBoolean                            TotalSuccessFlag = False;
  744.  
  745.         CheckPtrExistence(TrackList);
  746.         ListOfSelections = GetListOfSelectedItems(TrackList->List);
  747.         if (ListOfSelections != NIL)
  748.             {
  749.                 if (ArrayGetLength(ListOfSelections) >= 1)
  750.                     {
  751.                         TrackObjectRec*            TrackTemp;
  752.                         FileSpec*                        TempFileLocation;
  753.  
  754.                         TrackTemp = (TrackObjectRec*)ArrayGetElement(ListOfSelections,0);
  755.                         /* open the temporary file */
  756.                         TempFileLocation = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
  757.                             CODE4BYTES('\?','\?','\?','\?'));
  758.                         if (TempFileLocation != NIL)
  759.                             {
  760.                                 FileType*                            FileDescriptor;
  761.  
  762.                                 if (OpenFile(TempFileLocation,&FileDescriptor,eReadAndWrite))
  763.                                     {
  764.                                         BufferedOutputRec*        BufferedFile;
  765.  
  766.                                         BufferedFile = NewBufferedOutput(FileDescriptor);
  767.                                         if (BufferedFile != NIL)
  768.                                             {
  769.                                                 MyBoolean                            WriteSucceeded = False;
  770.  
  771.                                                 if (WriteBufferedOutput(BufferedFile,sizeof(MAGICSCRAPSTRING),
  772.                                                     MAGICSCRAPSTRING))
  773.                                                     {
  774.                                                         if (TrackObjectWriteDataOut(TrackTemp,BufferedFile)
  775.                                                             == eFileLoadNoError)
  776.                                                             {
  777.                                                                 WriteSucceeded = True;
  778.                                                             }
  779.                                                     }
  780.                                                 if (EndBufferedOutput(BufferedFile) && WriteSucceeded)
  781.                                                     {
  782.                                                         char*                            Buffer;
  783.                                                         long                            NumberOfBytes;
  784.  
  785.                                                         NumberOfBytes = GetFileLength(FileDescriptor);
  786.                                                         Buffer = AllocPtrCanFail(NumberOfBytes,
  787.                                                             "TrackListCopyObject:  scrap buffer");
  788.                                                         if (Buffer != NIL)
  789.                                                             {
  790.                                                                 if (SetFilePosition(FileDescriptor,0))
  791.                                                                     {
  792.                                                                         if (0 == ReadFromFile(FileDescriptor,
  793.                                                                             Buffer,NumberOfBytes))
  794.                                                                             {
  795.                                                                                 if (SetScrapToThis(Buffer))
  796.                                                                                     {
  797.                                                                                         TotalSuccessFlag = True;
  798.                                                                                     }
  799.                                                                             }
  800.                                                                     }
  801.                                                                 ReleasePtr(Buffer);
  802.                                                             }
  803.                                                     }
  804.                                             }
  805.                                         CloseFile(FileDescriptor);
  806.                                     }
  807.                                 DeleteFile(TempFileLocation);
  808.                                 DisposeFileSpec(TempFileLocation);
  809.                             }
  810.                     }
  811.                 DisposeArray(ListOfSelections);
  812.             }
  813.         return TotalSuccessFlag;
  814.     }
  815.  
  816.  
  817. /* try to paste the clipboard in as a track.  returns False if it failed or the */
  818. /* clipboard did not contain a track. */
  819. MyBoolean                        TrackListPasteObject(TrackListRec* TrackList)
  820.     {
  821.         MyBoolean                    TotalSuccessFlag = False;
  822.         char*                            Scrap;
  823.  
  824.         CheckPtrExistence(TrackList);
  825.         Scrap = GetCopyOfScrap();
  826.         if (Scrap != NIL)
  827.             {
  828.                 FileSpec*                    TempFileLocation;
  829.  
  830.                 TempFileLocation = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
  831.                     CODE4BYTES('\?','\?','\?','\?'));
  832.                 if (TempFileLocation != NIL)
  833.                     {
  834.                         FileType*                            FileDescriptor;
  835.  
  836.                         if (OpenFile(TempFileLocation,&FileDescriptor,eReadAndWrite))
  837.                             {
  838.                                 BufferedOutputRec*        BufferedFile;
  839.  
  840.                                 BufferedFile = NewBufferedOutput(FileDescriptor);
  841.                                 if (BufferedFile != NIL)
  842.                                     {
  843.                                         MyBoolean                            WriteSucceeded = False;
  844.  
  845.                                         if (WriteBufferedOutput(BufferedFile,PtrSize(Scrap),Scrap))
  846.                                             {
  847.                                                 WriteSucceeded = True;
  848.                                             }
  849.                                         if (EndBufferedOutput(BufferedFile) && WriteSucceeded)
  850.                                             {
  851.                                                 TotalSuccessFlag = TrackListPasteFromFile(TrackList,
  852.                                                     FileDescriptor);
  853.                                             }
  854.                                     }
  855.                                 CloseFile(FileDescriptor);
  856.                             }
  857.                         DeleteFile(TempFileLocation);
  858.                         DisposeFileSpec(TempFileLocation);
  859.                     }
  860.                 ReleasePtr(Scrap);
  861.             }
  862.         return TotalSuccessFlag;
  863.     }
  864.  
  865.  
  866. /* try to paste the track object in from the file */
  867. MyBoolean                        TrackListPasteFromFile(TrackListRec* TrackList,
  868.                                             struct FileType* File)
  869.     {
  870.         MyBoolean                    TotalSuccessFlag = False;
  871.  
  872.         CheckPtrExistence(TrackList);
  873.         if (SetFilePosition(File,0))
  874.             {
  875.                 BufferedInputRec*    InputFile;
  876.  
  877.                 InputFile = NewBufferedInput(File);
  878.                 if (InputFile != NIL)
  879.                     {
  880.                         char                            HeaderTest[sizeof(MAGICSCRAPSTRING)];
  881.  
  882.                         if (ReadBufferedInput(InputFile,sizeof(MAGICSCRAPSTRING),HeaderTest))
  883.                             {
  884.                                 if (MemEqu(MAGICSCRAPSTRING,HeaderTest,sizeof(MAGICSCRAPSTRING)))
  885.                                     {
  886.                                         TrackObjectRec*                TrackTemp EXECUTE(= (TrackObjectRec*)0x81818181);
  887.  
  888.                                         if (eFileLoadNoError == TrackObjectNewFromFile(&TrackTemp,InputFile,
  889.                                             TrackList->CodeCenter,TrackList->MainWindow,TrackList))
  890.                                             {
  891.                                                 CheckPtrExistence(TrackTemp);
  892.                                                 /* add it to the scrolling object list */
  893.                                                 if (!InsertStringListElement(TrackList->List,NIL,NIL,TrackTemp,True))
  894.                                                     {
  895.                                                      FailurePoint:
  896.                                                         DisposeTrackObject(TrackTemp);
  897.                                                     }
  898.                                                  else
  899.                                                     {
  900.                                                         MainWindowDeselectAllOtherStringLists(TrackList->MainWindow,TrackList);
  901.                                                         SelectStringListElement(TrackList->List,TrackTemp);
  902.                                                         MakeStringListSelectionVisible(TrackList->List);
  903.                                                         /* add it to the array */
  904.                                                         if (!ArrayAppendElement(TrackList->TrackArray,TrackTemp))
  905.                                                             {
  906.                                                                 RemoveStringListElement(TrackList->List,TrackTemp,True);
  907.                                                                 goto FailurePoint;
  908.                                                             }
  909.                                                          else
  910.                                                             {
  911.                                                                 /* change the name in the list */
  912.                                                                 TrackListTrackNameChanged(TrackList,TrackTemp);
  913.                                                                 TotalSuccessFlag = True;
  914.                                                                 TrackList->TrackListChanged = True;
  915.                                                             }
  916.                                                     }
  917.                                             }
  918.                                     }
  919.                             }
  920.                     }
  921.                 EndBufferedInput(InputFile);
  922.             }
  923.         return TotalSuccessFlag;
  924.     }
  925.